/**
 * This file is a part of qloudgen-sec. 
 * You can redistribute qloudgen-sec and/or modify it under the terms of the Lesser GNU General Public License version 3. 
 * qloudgen-sec is distributed WITHOUT ANY WARRANTY. 
 *
 * See the Lesser GNU General Public License for more details at http://www.gnu.org/licenses/. 
 **/
package org.qloudgen.sec.shiro.session;

import java.io.Serializable;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.CachingSessionDAO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>Title: Cached Session Implementation</p>
 * <p>Description: Wrappered session cache implementation for osgi service.</p>
 * <p>Copyright: qloudgen/sec 2014</p>
 * @author <a href="mailto:hyq.dd.sun@gmail.com">glue.3M</a>
 */
public class EnterpriseCacheSessionDAO extends CachingSessionDAO {
	/**
	 * Log output.
	 */
	private final static Logger logger = LoggerFactory.getLogger( EnterpriseCacheSessionDAO.class );
	
	/**
	 * Default constructor.
	 */
	public EnterpriseCacheSessionDAO() {
		logger.info( "Current session cache name is...{}" , getActiveSessionsCacheName() );
	}
	
	/**
	 * Generate session id for current session such as SimpleSession.
	 *
	 * @see SessionsSecurityManager.start(SessionContext context)
	 * @see AbstractNativeSessionManager.start(SessionContext context)
	 * @see AbstractValidatingSessionManager.createSession(SessionContext context)
	 * @see DefaultSessionManager.doCreateSession(SessionContext context)
	 * @see CachingSessionDAO.create(Session session)
	 * @see CachingSessionDAO.cache(Session session,Serializable sessionId);
	 * @see AbstractSessionDAO.create(Session session)
	 * @see EnterpriseCacheSessionDAO.doCreate(Session session)
	 * @see AbstractNativeSessionManager.createExposedSession(Session session,SessionContext context)
	 *
	 * @param session
	 * @return Serializable
	 */
	protected Serializable doCreate(Session session) {
		//
		Serializable sessionId = generateSessionId( session );
		//
		assignSessionId( session , sessionId );
		//
		logger.debug( "Current cached session will be created...{}" , session );
		//
		return sessionId;
	}
	
	/**
	 * Retrieve current session by id.
	 *
	 * @see SessionsSecurityManager.getSession(SessionKey key)
	 * @see AbstractNativeSessionManager.getSession(SessionKey key)
	 * @see AbstractValidatingSessionManager.doGetSession(SessionKey key)
	 * @see DefaultSessionManager.retrieveSession(SessionContext context)
	 * @see CachingSessionDAO.readSession(Serializable sessionId)
	 * @see CachingSessionDAO.getCachedSession(Serializable sessionId)
	 * @see AbstractSessionDAO.readSession(Serializable sessionId)
	 * @see EnterpriseCacheSessionDAO.doReadSession(Serializable sessionId)
	 *
	 * @param sessionId
	 * @return Session
	 */
	protected Session doReadSession(Serializable sessionId) {
		//
		logger.trace( "Current cached sesssion will be read...{}" , sessionId );
		/**
		 * Only when getCachedSession return null.
		 */
		return null;
	}
	
	/**
	 * Update current session by id.
	 *
	 * @see DefaultSessionManager.onChange(Session session)
	 * @see DelegatingSession
	 *
	 * @param Session
	 */
	protected void doUpdate(Session session) {
		logger.trace( "Current cached session will be updated...{}" , session );
	}
	
	/**
	 * Delete current session by id.
	 *
	 * @see DefaultSessionManager.delete(Session session)
	 *
	 * @param Session
	 */
	protected void doDelete(Session session) {
		logger.trace( "Current cached session will be deleted...{}" , session );
	}
		
	/**
	 * Create session cache from current cache manager.
	 *
	 * @return Cache
	 */
	@Override
	protected Cache<Serializable,Session> createActiveSessionsCache() {
		//
		Cache<Serializable,Session> cache = super.createActiveSessionsCache();
		//
		logger.info( "Current session cache is...{}" , cache );
		//
		return cache;
	}
	
	/**
	 * Storage current session into cache.
	 *
	 * @param session
	 * @param sessionId
	 * @param cache
	 */
	@Override
	protected void cache(Session session , Serializable sessionId , Cache<Serializable,Session> cache) {
		//
		logger.debug( "Starting storage current session into cache...{},{}" , sessionId , cache.size() );
		//
		super.cache( session , sessionId , cache );
		//
		logger.debug( "Started storage current session into cache...{},{}" , sessionId , cache.size() );
	}
	
	/**
	 * Retrieve current session from cache.
	 *
	 * @param sessionId
	 * @param cache
	 * @return Session
	 */
	@Override
	protected Session getCachedSession(Serializable sessionId , Cache<Serializable,Session> cache) {
		//
		logger.trace( "Starting retrieve current session from cache...{}" , sessionId );
		//
		Session session = super.getCachedSession( sessionId , cache );
		//
		logger.trace( "Started retrieve current session from cache...{}" , session );
		//
		return session;
	}
	
	/**
	 * Remove current session from cache.
	 *
	 * @param Session
	 */
	@Override
	protected void uncache(Session session) {
		//
		logger.trace( "Starting remove current session from cache...{},{}" , session.getId() , getActiveSessionsCache().size() );
		//
		super.uncache( session );
		//
		logger.trace( "Started remove current session from cache...{},{}" , session.getId() , getActiveSessionsCache().size() );
	}
}